#pragma once
#include "Connection.hpp"
#include "LoopThreadPool.hpp"
#include "Accept.hpp"

class TcpServer
{
private:
    uint64_t _id;   // 一个自增的id
    uint16_t _port; // 端口号
    int _timeout;   // 超时时间

    bool _enable_inactive_release; // 是否启用非活跃连接销毁
    EventLoop _baseloop;           // 主Reactor
    Acceptor _acceptor;
    LoopThreadPool _thread_pool;   // 从属Reactor线程池

    // 保存各个连接对应的PtrConnection对象
    std::unordered_map<uint64_t, PtrConnection> _conns;

    using ConnectionCallback = std::function<void(const PtrConnection &cb)>;
    using MessageCallback = std::function<void(const PtrConnection &cb, Buffer *)>;
    using ClosedCallback = std::function<void(const PtrConnection &cb)>;
    using AnyEventCallback = std::function<void(const PtrConnection &cb)>;
    using Functor = std::function<void()>;

    // 用户传入的回调函数
    ConnectionCallback _connection_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _anyevent_callback;

private:
    void RunAfterInLoop(const Functor &task, int delay)
    {
        _id++;
        _baseloop.TimerAdd(_id, delay, task);
    }
    //为连接构造一个Connection进行管理
    void NewConnection(int fd)
    {
        _id++;
        PtrConnection conn(new Connection(_id, fd, _thread_pool.GetLoop()));
        //为连接设置回调函数
        conn->SetMessageCallback(_message_callback);
        conn->SetClosedCallback(_closed_callback);
        conn->SetConnectionCallback(_connection_callback);
        conn->SetAnyEventCallback(_anyevent_callback);
        conn->SetServerClosedCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));
        //启动非活跃连接销毁
        if(_enable_inactive_release)
            conn->EnableInactiveRelease(_timeout);
        //初始化连接
        conn->Established();
        _conns.insert(std::make_pair(_id, conn));
    }
    //将保存的连接数据移除的函数
    void RemoveConnectionInLoop(const PtrConnection &conn)
    {
        auto it = _conns.find(conn->Id());
        if(it == _conns.end())
            return;
        _conns.erase(it);
    }
    //从管理的连接中移除conn数据
    void RemoveConnection(const PtrConnection &conn)
    {
        _baseloop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
    }

public:
    TcpServer(int port) 
        : _id(0), _port(port), _enable_inactive_release(false), _acceptor(&_baseloop, port), _thread_pool(&_baseloop)
    {
    }
};